﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using WebSite.ActionFilter;
using WebSite.DAL.Db;
using WebSite.Db;
using WebSite.Models;
using WebSite.Models.BusinessModels;
using WebSite.Models.ViewModels;
using WebSite.Repositories;
using WebSite.Services;

namespace WebSite.Controllers
{
    public class OnlineMessengerController : ApiController
    {
        private IOnlineChatRepository _onlineChatRepository;
        private IAnswerPhone          _answerPhone;

        public OnlineMessengerController(IOnlineChatRepository repository,IAnswerPhone answerPhone)
        {
            _onlineChatRepository = repository;
            _answerPhone          = answerPhone;
        }

        public OnlineMessengerController()
            :this(/*new OnlineChatApplicationRepository(HttpContext.Current.Application)*/
                   new DbOnlineChatRepository("DbСontext"/*ConfigurationManager.ConnectionStrings["DbСontext"].ConnectionString*/), new AnswerPhone())
        {
        }

        [Authorize]
        [ActionName("ActiveMeetings")]
        public IEnumerable<MeetingSessionVM> GetActiveMeetings()
        {
            return _onlineChatRepository.GetActiveSessions();
        }

        [ActionName("MeetingSession")]
        public MeetingSessionVM GetMeetingSession()
        {
            HttpRequestWrapper context = new HttpRequestWrapper(HttpContext.Current.Request);
            String userIP = IPResolver.GetClientIpAddress(context);
            return _onlineChatRepository.CreateMeetingSession(userIP);
        }

        [ActionName("MeetingSession")]
        public MeetingSessionVM GetMeetingSession(String lastSessionId)
        {
            HttpRequestWrapper context = new HttpRequestWrapper(HttpContext.Current.Request);
            String userIP = IPResolver.GetClientIpAddress(context);

            Guid parseResult = Guid.Empty;
            MeetingSessionVM result = null;
            if (Guid.TryParse(lastSessionId, out parseResult))
            {
                result = _onlineChatRepository.GetMeetingSessionById(parseResult) ?? _onlineChatRepository.CreateMeetingSession(userIP);
            }
            else
            {
                result = _onlineChatRepository.CreateMeetingSession(userIP);
            }
            result.LastMessageId = 0;
            return result;
        }

        private void CreateMeetingMessage(Guid sessionId,MeetingMessageVM message)
        {
            _onlineChatRepository.AddMessageToSession(sessionId, message);
        }

        [HttpGet]
        [ActionName("MeetingMessages")]
        public IEnumerable<MeetingMessageVM> GetMeetingMessages([FromUri]MeetingSessionVM sessionVM)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    MeetingSessionVM session                  = _onlineChatRepository.GetMeetingSessionById(sessionVM.SessionId);
                    if (session == null)
                        throw new ArgumentOutOfRangeException();
                    IEnumerable<MeetingMessageVM> allMessages = _onlineChatRepository.LoadSessionMessages(session.SessionId, 0);
                    
                    if (_onlineChatRepository.StartBotProcessing(session.SessionId))
                    {
                        try
                        {
                            _answerPhone.ProcessMessageQueue(session, allMessages, this.CreateMeetingMessage);
                        }
                        finally
                        {
                            _onlineChatRepository.EndBotProcessing(session.SessionId);
                        }
                    }
                    
                    IEnumerable<MeetingMessageVM> messages    = _onlineChatRepository.LoadSessionMessages(session.SessionId, sessionVM.LastMessageId);
                    return messages;

                }
                catch(ArgumentOutOfRangeException)
                {
                    //Session no longer exists
                    throw new HttpException((int)HttpStatusCode.Conflict, "Session no longer exists");
                }
            }
            else
                {
                throw new HttpException((int)HttpStatusCode.BadRequest, "Paremeters being passed are corrupted");
            }
        }

        [HttpPost]
        public HttpResponseMessage ArchiveSession([FromBody]String sessionId)
        {
             Guid parseResult = Guid.Empty;
             if (Guid.TryParse(sessionId, out parseResult))
             {
                 MeetingSessionVM session = _onlineChatRepository.GetMeetingSessionById(parseResult);
                 IEnumerable<MeetingMessageVM> sessionMessages = _onlineChatRepository.LoadSessionMessages(parseResult, 0);
                 _onlineChatRepository.ArchiveSession(session, sessionMessages);
                 _onlineChatRepository.DeleteSession(parseResult);
                 return new HttpResponseMessage(HttpStatusCode.OK);
             }
             else
             {
                 return this.Request.CreateResponse(HttpStatusCode.NotFound);
             }
        }


        // POST api/onlinemessenger
        [HttpPost]
        public HttpResponseMessage Post([FromBody]SendMessageVM messageVM)
        {
            if (ModelState.IsValid)
            {
                MeetingMessageVM newMessage = new MeetingMessageVM(){
                    Author      = messageVM.Author,
                    MessageText = messageVM.Message,
                    PostedOn    = SmartTime.Now
                };
                newMessage = _onlineChatRepository.AddMessageToSession(messageVM.SessionId,newMessage);

                return Request.CreateResponse<MeetingMessageVM>(HttpStatusCode.Created, newMessage);
            }
            else
            {
                List<String> errors = new List<string>();
                foreach (var state in ModelState)
                {
                    foreach (var error in state.Value.Errors)
                    {
                        errors.Add(error.ErrorMessage);
                    }
                }
                return Request.CreateErrorResponse(HttpStatusCode.Forbidden, ModelState);
            }
        }
    }

}
